using System.Collections;
using protobuf.Protocol;
using UI;
using UnityEngine;
using Tools;

namespace Core.Net
{
    public partial class NetManager
    {
        //当前状态特殊处理服务器断线重连时候的请求
        public ServerErrorDealType SceneSpecialServerErrorDeal_OnReconnect = ServerErrorDealType.None;

        public RPCMsgManager RPC = new RPCMsgManager();


        //ACK队列，存放MSGID
        private ConcurrentHashSet<int> ackQueue = new ConcurrentHashSet<int>();

        public CTimerSystem TimerSystem = new CTimerSystem();

        public int CurrentSocketWaitTime = 20;

        /// <summary>
        /// 正在返回到登录页面，这个Bool避免多次重连错误
        /// </summary>
        public static bool IsReturningToLogin = false;

        #region 连接动画

        /// <summary>
        /// 启动一个带动画的RPC请求连接,不要直接调用
        /// </summary>
        public void PRCSendWithAnim(RPCAsyncResult res)
        {
            res.timerID = TimerSystem.CreateTimer(RPCMsgManager.TIMEOUT, tid =>
            {
                var rpcResult = res;
                //如果意外接收到了完成的数据
                if (!rpcResult.isCompleted) return;
                //停止超时计时器
                TimerSystem.DestroyTimer(rpcResult.timerID);
                rpcResult.isTimeOut = true;
                rpcResult.errorType = RPCErrorType.TimeOut;
                rpcResult.isCompleted = true;
                //处理RPC请求回调 
                RPC.DealRPCCallBack(rpcResult);
                rpcResult.Finish();
                //超时LOG
#if UNITY_EDITOR || DEVELOPMENT_BUILD
                Debug.LogWarning($"RPC超时rpcID={rpcResult.RPCID.ToString()}，msgID={rpcResult.MSGID}, 当前时间：{ServerTime.ToLocalTime().ToString()}");
#endif
            });
            StartCoroutine(IRPCNetAnim(res));
        }

        private IEnumerator IRPCNetAnim(RPCAsyncResult res)
        {
            //如果断网了，重新联网
            if (!IsConnected)
            {
                DoReconnectWithRPCResend(res);
            }
            else
            {
                SendRPCResult(res);
            }

            //等到连接成功并且服务器回信
            while (!res.isCompleted)
            {
                yield return new WaitForEndOfFrame();
            }
            yield return null;
        }

        #endregion


        /// <summary>
        /// 清除特定场景情况下设置的网络重连配置
        /// </summary>
        public void Clear_SceneSpecialServerErrorDeal_OnReconnect()
        {
            SceneSpecialServerErrorDeal_OnReconnect = ServerErrorDealType.None;
        }


        //重连
        void DoReconnectWithRPCResend(RPCAsyncResult _res)
        {
            //如果是完成的res，需要重置完成状态
            if (_res.isCompleted)
            {
                RPC.ResetRPCToUncompleted(_res);
            }
            if (IsConnected) return;
            Reconnect((success2, data) =>
            {
                var res = _res;
                if (success2)
                {
                    //发送之前的请求数据
                    RPC.DealRPCCall(res);
                }
                else
                {
                    //连接失败弹出提示框 
                    OpenRetryRPCMessageBox(res);
                }
            });
        }

        /// <summary>
        /// 当收到了RPC回复后的回调，用于关闭重试连接等窗口
        /// </summary>
        /// <param name="action"></param>
        internal void OnAfterRPCCallBack(RPCAsyncResult action)
        {
            //返回登录界面状态下不处理后续请求
            if (IsReturningToLogin) return;
            // 通用错误处理
            if (action.errorType != RPCErrorType.None)
            {
                if (action.protoType != ProtolcalType.RealTime)
                {
                    if (action.errorType == RPCErrorType.CustomDefineError)
                    {
                        //根据ID查找服务器请求错误信息
                        var id = action.errorData.Type;
                        HandleRPCCustomACKErrorCode(action, (uint) id);
                    }
                    else
                    {
                        // 不处理连接失败、超时的情况
                        if (action.errorType != RPCErrorType.TimeOut && action.errorType != RPCErrorType.ClearRPC)
                        {
                            var text = $"RPC请求{action.RPCID.ToString()}异常!";
                            //UIManager.inst.tips.ShowTips(text);
                        }
                    }
                }
            }
            // A协议弹出窗口处理连接问题
            if (action.protoType == ProtolcalType.Ahead)
            {
                if (action.errorType == RPCErrorType.None || action.errorType == RPCErrorType.CustomDefineError)
                {
                    //关闭之前打开的尝试重连UI界面
                    if (CheckHasNetMessageBox(ServerErrorDealType.CloseNetAndResend))
                    {
                    }
                }
                if (action.errorType == RPCErrorType.CustomDefineError)
                {
                }
                else if (action.errorType == RPCErrorType.TimeOut)
                {
                    //如果是登录协议超时，请重新登录。
                    if (action.RPCID == ProtoType.AccountLogin)
                    {
                        //UIManager.inst.messageBox.ShowOK("网络已经断开，请重新登录", GameManager.inst.ReLogin);
                    }
                    else
                    {
                        //如果超时，直接认定为断线，避免后面数据导致前面逻辑错误
#if UNITY_EDITOR
                        Debug.LogError($"协议:{(ProtoType) action.RPCID}超时");
#endif
                        Close();
#if DEVELOPMENT_BUILD
                        if (!string.IsNullOrEmpty(RPC.LoginToken))
                        {
                            //连接失败弹出提示框 
                            OpenRetryRPCMessageBox(action);
                        }
                        else
                        {
                            UIManager.inst.tips.ShowTips("连接超时,请重新登录");
                        }
#else
                        //连接失败弹出提示框 
                        OpenRetryRPCMessageBox(action);
#endif
                    }
                } //连接失败，没有什么特殊处理
            }
        }

        internal void SendRPCResult(RPCAsyncResult res)
        {
            if (res != null)
            {
                var frame = res.frame;
                res.sendTime = NetHelper.GetEnvironmentTickCount();
                frame.RPCID = (short) res.RPCID;
                frame.MSGID = res.MSGID;
                frame.IsSendAutoConsumed = res.protoType == ProtolcalType.RealTime || res.protoType == ProtolcalType.none;
                PutInRPCSendQueue(frame);
            }
        }

        private void PutInRPCSendQueue(Frame frame)
        {
            if (frame == null) return;
            // 队列为空直接发送
            // if (IsConnected && sendQueue.Count == 0)
            // {
            SocketSend(frame);
            //  }
            //  else
            //  {
            //      //压入发送队列准备发送
            //      sendQueue.Enqueue(frame);
            //  }
            //压入ACK队列
            ackQueue.Add(frame.MSGID);
        }


#if UNITY_EDITOR
        public int[] msgIDTime = new int[500];
#endif

        internal void ReceiveRPC(Frame frame)
        {
            RPC.ReceverRPCCallStatic(frame.RPCID, frame.MSGID, frame.GetContent());
        }

        /// <summary>
        /// 处理服务器发过来的错误消息
        /// </summary>
        public void HandleRPCCustomACKErrorCode(RPCAsyncResult action, uint errorcode)
        {
            if (StaticConfigure.Server.ErrorDict.TryGetValue(errorcode, out var cfg))
            {
                if (cfg.IsShutDownImmediately)
                {
                    Close();
                }
                switch (cfg.ServerErrorShowType)
                {
                    case ServerErrorShowType.None:
                        HandleRPCACKErrorCodeHelper(cfg.ServerErrorDealType);
                        break;
                    case ServerErrorShowType.ShowOkwindow:
                        //UIManager.inst.messageBox.ShowOK(cfg.DescriptionID.GetLocal(UIStringType.Server), () => HandleRPCACKErrorCodeHelper(cfg.ServerErrorDealType));
                        break;
                    case ServerErrorShowType.ShowOkcancelWindow:
                        //UIManager.inst.messageBox.ShowOKCancel(cfg.DescriptionID.GetLocal(UIStringType.Server), () => HandleRPCACKErrorCodeHelper(cfg.ServerErrorDealType));
                        break;
                    case ServerErrorShowType.ShowTips:
                        //UIManager.inst.tips.ShowTips(cfg.DescriptionID.GetLocal(UIStringType.Server));
                        HandleRPCACKErrorCodeHelper(cfg.ServerErrorDealType);
                        break;
                }
#if UNITY_EDITOR
                Debug.LogError(action == null ? $"服务器推送错误消息，错误代号为:{errorcode},内容为:{cfg.DescriptionID.GetLocal(UIStringType.Server)}" : $"服务器推送错误消息，协议:{action.RPCID},错误代号为:{errorcode},内容为:{cfg.DescriptionID.GetLocal(UIStringType.Server)},处理方式:{cfg.ServerErrorDealType}");
#endif
            }
            else
            {
#if UNITY_EDITOR
                Debug.LogError(action == null ? $"服务器推送错误消息，错误代号为:{errorcode}" : $"协议:{action.RPCID},错误代号为:{errorcode}");
#endif
            }
        }

        /// <summary>
        /// 辅助处理服务器传输的自定义错误消息
        /// </summary>
        private void HandleRPCACKErrorCodeHelper(ServerErrorDealType type)
        {
            switch (type)
            {
                case ServerErrorDealType.None:
                    break;
                case ServerErrorDealType.ReturnToLogin:
                    BackToLogin();
                    break;
                case ServerErrorDealType.RebootGame:
                    GameManager.inst.RestartGame();
                    break;
                case ServerErrorDealType.ReconnectNet:
                    Reconnect();
                    break;
                case ServerErrorDealType.CloseNetAndResend:
                    Close();
                    Reconnect();
                    break;
            }
        }
    }
}